﻿// -------------------------------------------------------------------------
//    @FileName         :    NFMathOp.h
//    @Author           :    Gao.Yi
//    @Date             :    2025-09-30
//    @Email			:    445267987@qq.com
//    @Module           :    NFMathOp
//    @Desc             :
//
// -------------------------------------------------------------------------

#pragma once

#include "NFComm/NFCore/NFPlatform.h"
#include "NFLogMgr.h"
#include "NFStackTrace.h"
#include <float.h>

#ifndef MIN
#define MIN(a,b)            (((a)<=(b))?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b)            (((a)>=(b))?(a):(b))
#endif

#ifndef MINEXTRA
#define MINEXTRA(a,b,c,d)   (((a)<=(b))?(c):(d))
#endif
#ifndef MAXEXTRA
#define MAXEXTRA(a,b,c,d)   (((a)>=(b))?(c):(d))
#endif

// ADD 系列宏：安全地将值v加到p上，并限制在类型范围内
#define ADD_CHAR(p,v) do { \
    int __old = (p); \
    int __result = (int)(p) + (v); \
    if ((v) > 0) { \
        if (__result > INT8_MAX) { \
            LOG_WARN(0, -1, "ADD_CHAR overflow: p={}, v={}, result={} > INT8_MAX, clamped to INT8_MAX. Stack: {}", __old, (v), __result, TRACE_STACK()); \
            p = INT8_MAX; \
        } else { \
            p = __result; \
        } \
    } else { \
        if (__result < INT8_MIN) { \
            LOG_WARN(0, -1, "ADD_CHAR underflow: p={}, v={}, result={} < INT8_MIN, clamped to INT8_MIN. Stack: {}", __old, (v), __result, TRACE_STACK()); \
            p = INT8_MIN; \
        } else { \
            p = __result; \
        } \
    } \
} while(0)

#define ADD_UCHAR(p,v) do { \
    int __old = (p); \
    int __result = (int)(p) + (v); \
    if ((v) > 0) { \
        if (__result > UINT8_MAX) { \
            LOG_WARN(0, -1, "ADD_UCHAR overflow: p={}, v={}, result={} > UINT8_MAX, clamped to UINT8_MAX. Stack: {}", __old, (v), __result, TRACE_STACK()); \
            p = UINT8_MAX; \
        } else { \
            p = __result; \
        } \
    } else { \
        if (__result < 0) { \
            LOG_WARN(0, -1, "ADD_UCHAR underflow: p={}, v={}, result={} < 0, clamped to 0. Stack: {}", __old, (v), __result, TRACE_STACK()); \
            p = 0; \
        } else { \
            p = __result; \
        } \
    } \
} while(0)

#define ADD_WORD(p,v) do { \
    int __old = (p); \
    int __result = (int)(p) + (v); \
    if ((v) > 0) { \
        if (__result > INT16_MAX) { \
            LOG_WARN(0, -1, "ADD_WORD overflow: p={}, v={}, result={} > INT16_MAX, clamped to INT16_MAX. Stack: {}", __old, (v), __result, TRACE_STACK()); \
            p = INT16_MAX; \
        } else { \
            p = __result; \
        } \
    } else { \
        if (__result < INT16_MIN) { \
            LOG_WARN(0, -1, "ADD_WORD underflow: p={}, v={}, result={} < INT16_MIN, clamped to INT16_MIN. Stack: {}", __old, (v), __result, TRACE_STACK()); \
            p = INT16_MIN; \
        } else { \
            p = __result; \
        } \
    } \
} while(0)

#define ADD_UWORD(p,v) do { \
    int __old = (p); \
    int __result = (int)(p) + (v); \
    if ((v) > 0) { \
        if (__result > UINT16_MAX) { \
            LOG_WARN(0, -1, "ADD_UWORD overflow: p={}, v={}, result={} > UINT16_MAX, clamped to UINT16_MAX. Stack: {}", __old, (v), __result, TRACE_STACK()); \
            p = UINT16_MAX; \
        } else { \
            p = __result; \
        } \
    } else { \
        if (__result < 0) { \
            LOG_WARN(0, -1, "ADD_UWORD underflow: p={}, v={}, result={} < 0, clamped to 0. Stack: {}", __old, (v), __result, TRACE_STACK()); \
            p = 0; \
        } else { \
            p = __result; \
        } \
    } \
} while(0)

// SET 系列宏：安全地将值v设置给p，并限制在类型范围内
#define SET_CHAR(p,v) do { \
    if ((v) > INT8_MAX) { \
        LOG_WARN(0, -1, "SET_CHAR overflow: v={} > INT8_MAX, clamped to INT8_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = INT8_MAX; \
    } else if ((v) < INT8_MIN) { \
        LOG_WARN(0, -1, "SET_CHAR underflow: v={} < INT8_MIN, clamped to INT8_MIN. Stack: {}", (v), TRACE_STACK()); \
        p = INT8_MIN; \
    } else { \
        p = (v); \
    } \
} while(0)

#define SET_UCHAR(p,v) do { \
    if ((v) > UINT8_MAX) { \
        LOG_WARN(0, -1, "SET_UCHAR overflow: v={} > UINT8_MAX, clamped to UINT8_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = UINT8_MAX; \
    } else if ((v) < 0) { \
        LOG_WARN(0, -1, "SET_UCHAR underflow: v={} < 0, clamped to 0. Stack: {}", (v), TRACE_STACK()); \
        p = 0; \
    } else { \
        p = (v); \
    } \
} while(0)

#define SET_WORD(p,v) do { \
    if ((v) > INT16_MAX) { \
        LOG_WARN(0, -1, "SET_WORD overflow: v={} > INT16_MAX, clamped to INT16_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = INT16_MAX; \
    } else if ((v) < INT16_MIN) { \
        LOG_WARN(0, -1, "SET_WORD underflow: v={} < INT16_MIN, clamped to INT16_MIN. Stack: {}", (v), TRACE_STACK()); \
        p = INT16_MIN; \
    } else { \
        p = (v); \
    } \
} while(0)

#define SET_UWORD(p,v) do { \
    if ((v) > UINT16_MAX) { \
        LOG_WARN(0, -1, "SET_UWORD overflow: v={} > UINT16_MAX, clamped to UINT16_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = UINT16_MAX; \
    } else if ((v) < 0) { \
        LOG_WARN(0, -1, "SET_UWORD underflow: v={} < 0, clamped to 0. Stack: {}", (v), TRACE_STACK()); \
        p = 0; \
    } else { \
        p = (v); \
    } \
} while(0)

#define ADD_UINT(p,v) do { \
    unsigned int __old = (p); \
    unsigned int __t = (p) + (v); \
    if ((v) > 0) { \
        if (__t > (p)) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_UINT overflow: p={}, v={}, result would overflow, clamped to UINT32_MAX. Stack: {}", __old, (v), TRACE_STACK()); \
            p = UINT32_MAX; \
        } \
    } else { \
        if (__t <= (p)) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_UINT underflow: p={}, v={}, result would underflow, clamped to 0. Stack: {}", __old, (v), TRACE_STACK()); \
            p = 0; \
        } \
    } \
} while(0)

#define ADD_INT(p,v) do { \
    int __old = (p); \
    int __t = (p) + (v); \
    if ((v) > 0) { \
        if (__t > (p)) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_INT overflow: p={}, v={}, result would overflow, clamped to INT32_MAX. Stack: {}", __old, (v), TRACE_STACK()); \
            p = INT32_MAX; \
        } \
    } else { \
        if (__t <= (p)) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_INT underflow: p={}, v={}, result would underflow, clamped to INT32_MIN. Stack: {}", __old, (v), TRACE_STACK()); \
            p = INT32_MIN; \
        } \
    } \
} while(0)

#define ADD_UINT64(p,v) do { \
    uint64_t __old = (p); \
    uint64_t __t = (p) + (v); \
    if ((v) > 0) { \
        if (__t > (p)) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_UINT64 overflow: p={}, v={}, result would overflow, clamped to UINT64_MAX. Stack: {}", __old, (v), TRACE_STACK()); \
            p = UINT64_MAX; \
        } \
    } else { \
        if (__t <= (p)) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_UINT64 underflow: p={}, v={}, result would underflow, clamped to 0. Stack: {}", __old, (v), TRACE_STACK()); \
            p = 0; \
        } \
    } \
} while(0)

#define ADD_INT64(p,v) do { \
    int64_t __old = (p); \
    int64_t __t = (p) + (v); \
    if ((v) > 0) { \
        if (__t > (p)) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_INT64 overflow: p={}, v={}, result would overflow, clamped to INT64_MAX. Stack: {}", __old, (v), TRACE_STACK()); \
            p = INT64_MAX; \
        } \
    } else { \
        if (__t <= (p)) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_INT64 underflow: p={}, v={}, result would underflow, clamped to INT64_MIN. Stack: {}", __old, (v), TRACE_STACK()); \
            p = INT64_MIN; \
        } \
    } \
} while(0)

#define SET_UINT(p,v) do { \
    if ((v) < 0) { \
        LOG_WARN(0, -1, "SET_UINT underflow: v={} < 0, clamped to 0. Stack: {}", (v), TRACE_STACK()); \
        p = 0; \
    } else if ((unsigned int)(v) > UINT32_MAX) { \
        LOG_WARN(0, -1, "SET_UINT overflow: v={} > UINT32_MAX, clamped to UINT32_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = UINT32_MAX; \
    } else { \
        p = (v); \
    } \
} while(0)

#define SET_INT(p,v) do { \
    if ((v) > INT32_MAX) { \
        LOG_WARN(0, -1, "SET_INT overflow: v={} > INT32_MAX, clamped to INT32_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = INT32_MAX; \
    } else if ((v) < INT32_MIN) { \
        LOG_WARN(0, -1, "SET_INT underflow: v={} < INT32_MIN, clamped to INT32_MIN. Stack: {}", (v), TRACE_STACK()); \
        p = INT32_MIN; \
    } else { \
        p = (v); \
    } \
} while(0)

#define SET_UINT64(p,v) do { \
    if ((v) < 0) { \
        LOG_WARN(0, -1, "SET_UINT64 underflow: v={} < 0, clamped to 0. Stack: {}", (v), TRACE_STACK()); \
        p = 0; \
    } else if ((uint64_t)(v) > UINT64_MAX) { \
        LOG_WARN(0, -1, "SET_UINT64 overflow: v={} > UINT64_MAX, clamped to UINT64_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = UINT64_MAX; \
    } else { \
        p = (v); \
    } \
} while(0)

#define SET_INT64(p,v) do { \
    if ((v) > INT64_MAX) { \
        LOG_WARN(0, -1, "SET_INT64 overflow: v={} > INT64_MAX, clamped to INT64_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = INT64_MAX; \
    } else if ((v) < INT64_MIN) { \
        LOG_WARN(0, -1, "SET_INT64 underflow: v={} < INT64_MIN, clamped to INT64_MIN. Stack: {}", (v), TRACE_STACK()); \
        p = INT64_MIN; \
    } else { \
        p = (v); \
    } \
} while(0)

// 浮点数类型的 ADD 和 SET 宏
#define ADD_FLOAT(p,v) do { \
    float __old = (p); \
    float __t = (p) + (v); \
    if ((v) > 0) { \
        if (__t > (p) && __t <= FLT_MAX) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_FLOAT overflow: p={}, v={}, result would overflow, clamped to FLT_MAX. Stack: {}", __old, (v), TRACE_STACK()); \
            p = FLT_MAX; \
        } \
    } else { \
        if (__t <= (p) && __t >= -FLT_MAX) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_FLOAT underflow: p={}, v={}, result would underflow, clamped to -FLT_MAX. Stack: {}", __old, (v), TRACE_STACK()); \
            p = -FLT_MAX; \
        } \
    } \
} while(0)

#define SET_FLOAT(p,v) do { \
    if ((v) > FLT_MAX) { \
        LOG_WARN(0, -1, "SET_FLOAT overflow: v={} > FLT_MAX, clamped to FLT_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = FLT_MAX; \
    } else if ((v) < -FLT_MAX) { \
        LOG_WARN(0, -1, "SET_FLOAT underflow: v={} < -FLT_MAX, clamped to -FLT_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = -FLT_MAX; \
    } else { \
        p = (v); \
    } \
} while(0)

#define ADD_DOUBLE(p,v) do { \
    double __old = (p); \
    double __t = (p) + (v); \
    if ((v) > 0) { \
        if (__t > (p) && __t <= DBL_MAX) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_DOUBLE overflow: p={}, v={}, result would overflow, clamped to DBL_MAX. Stack: {}", __old, (v), TRACE_STACK()); \
            p = DBL_MAX; \
        } \
    } else { \
        if (__t <= (p) && __t >= -DBL_MAX) { \
            p = __t; \
        } else { \
            LOG_WARN(0, -1, "ADD_DOUBLE underflow: p={}, v={}, result would underflow, clamped to -DBL_MAX. Stack: {}", __old, (v), TRACE_STACK()); \
            p = -DBL_MAX; \
        } \
    } \
} while(0)

#define SET_DOUBLE(p,v) do { \
    if ((v) > DBL_MAX) { \
        LOG_WARN(0, -1, "SET_DOUBLE overflow: v={} > DBL_MAX, clamped to DBL_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = DBL_MAX; \
    } else if ((v) < -DBL_MAX) { \
        LOG_WARN(0, -1, "SET_DOUBLE underflow: v={} < -DBL_MAX, clamped to -DBL_MAX. Stack: {}", (v), TRACE_STACK()); \
        p = -DBL_MAX; \
    } else { \
        p = (v); \
    } \
} while(0)

#define PERCENT_INT(v,p) ((int)((int64_t)(v)*(p)/100))

#define COMPARE_PERCENT(v,p) ((p)==0?((v)==0?100:0):(int)((int64_t)(v)*100/(p)))

#define PERCENT_ADD_INT(v,p) ((int)((int64_t)(v)*(100+p)/100))
#define PERCENT_DEC_INT(v,p) ((p)<100)?((int)(((int64_t)(v)*(100-p))/100)):0